/*
 Copyright (C) 2012  Nikos Siatras
 This program is free software: you can redistribute it and/or modify
 it under the terms of the GNU General Public License as published by
 the Free Software Foundation, either version 3 of the License, or
 (at your option) any later version.

 This program is distributed in the hope that it will be useful,
 but WITHOUT ANY WARRANTY; without even the implied warranty of
 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 GNU General Public License for more details.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.*/
package ncore_tcp_port_forward.UI;

import java.awt.Dimension;
import java.awt.Image;
import java.awt.SystemTray;
import java.awt.Toolkit;
import java.awt.TrayIcon;
import java.io.*;
import java.util.ArrayList;
import javax.swing.ImageIcon;
import javax.swing.JFrame;
import javax.swing.JOptionPane;
import javax.swing.table.DefaultTableModel;
import ncore_tcp_port_forward.Core.TCPForward;
import ncore_tcp_port_forward.Serialization.Serializer;

/**
 *
 * @author Nikos Siatras
 */
public class frmMain extends javax.swing.JFrame
{

    public ArrayList fTCPForwards = new ArrayList();
    private final Object fAddRemoveTCPForwardsLock = new Object();
    private TCPForward fSelectedTCPForward;
    private Thread fUpdateTCPForwardsThread;

    /**
     * Creates new form frmMain
     */
    public frmMain()
    {
        initComponents();

        //setIconImage(Toolkit.getDefaultToolkit().getImage(getClass().getResource("TCPForward.png")));

        StartUpdatingTCPForwards();
        Load();

        try
        {
            if (SystemTray.isSupported())
            {
                ImageIcon icon = new ImageIcon("Images/TCPForward.png");

                TrayIcon tray = new TrayIcon(icon.getImage(), "nCore TCP Forward", popupMenuTray);

                SystemTray.getSystemTray().add(tray);
            }
        }
        catch (Exception ex)
        {
            System.err.println(ex.getMessage());
        }

    }

    private void StartUpdatingTCPForwards()
    {
        fUpdateTCPForwardsThread = new Thread(new TCPForwardsTableUpdateThread(this));
        fUpdateTCPForwardsThread.start();
    }

    /**
     * Add TCP forward to fTCPForwards Arraylist
     *
     * @param forward is the TCPForward to add
     */
    public void AddTCPForward(TCPForward forward)
    {
        synchronized (fAddRemoveTCPForwardsLock)
        {
            fTCPForwards.add(forward);
        }
    }

    /**
     * Remove TCP forward from fTCPForwards Arraylist
     *
     * @param forward is the TCPForward to remove
     */
    public void RemoveTCPForward(TCPForward forward)
    {
        synchronized (fAddRemoveTCPForwardsLock)
        {
            ArrayList forwards = fTCPForwards;
            for (int i = 0; i < forwards.size(); i++)
            {
                TCPForward temp = (TCPForward) forwards.get(i);

                if (temp.getName().equals(forward.getName()))
                {
                    temp.Stop();
                    forwards.remove(temp);
                    break;
                }
            }
        }
    }

    public void UpdateTCPForwardsTable()
    {
        synchronized (fAddRemoveTCPForwardsLock)
        {
            // Add TCP Forwards to jTableTCPForwards
            for (int i = 0; i < fTCPForwards.size(); i++)
            {
                TCPForward forward = (TCPForward) fTCPForwards.get(i);
                boolean exists = false;
                for (int x = 0; x < jTableTCPForwards.getRowCount(); x++)
                {
                    if (jTableTCPForwards.getValueAt(x, 1).toString().equals(forward.getName()))
                    {
                        exists = true;
                        // Update data
                        if (forward.isStarted())
                        {
                            jTableTCPForwards.setValueAt("On", x, 0);
                        }
                        else
                        {
                            jTableTCPForwards.setValueAt("Off", x, 0);
                        }
                        jTableTCPForwards.setValueAt(forward.getLocalIPAddress() + ":" + forward.getLocalPort(), x, 2);
                        jTableTCPForwards.setValueAt(forward.getRemoteIPAddress() + ":" + forward.getRemotePort(), x, 3);
                        jTableTCPForwards.setValueAt(forward.getCurrentConnectionsNumber() + "/" + forward.getMaxConnections(), x, 4);
                        jTableTCPForwards.setValueAt(forward.getBytesIn() + "/" + forward.getBytesOut(), x, 5);
                        break;
                    }
                }

                if (!exists)
                {
                    DefaultTableModel model = (DefaultTableModel) jTableTCPForwards.getModel();
                    String data[] = new String[6];
                    data[0] = "";
                    data[1] = forward.getName();
                    data[2] = "";
                    data[3] = "";
                    data[4] = "";
                    data[5] = "";
                    model.insertRow(model.getRowCount(), data);
                    jTableTCPForwards.setModel(model);
                }
            }

            // Remove deleted TCP forwards from jTableTCPForwards
            for (int i = 0; i < jTableTCPForwards.getRowCount(); i++)
            {
                boolean exists = false;
                for (int x = 0; x < fTCPForwards.size(); x++)
                {
                    if (((TCPForward) fTCPForwards.get(x)).getName().equals(jTableTCPForwards.getValueAt(i, 1)))
                    {
                        exists = true;
                        break;
                    }
                }

                if (!exists)
                {
                    DefaultTableModel model = (DefaultTableModel) jTableTCPForwards.getModel();
                    model.removeRow(i);
                    jTableTCPForwards.setModel(model);
                }
            }
        }
    }

    public void Save()
    {
        synchronized (fAddRemoveTCPForwardsLock)
        {
            File folder = new File("TCPForwards");
            folder.mkdir();

            for (int i = 0; i < fTCPForwards.size(); i++)
            {
                try
                {
                    TCPForward forward = (TCPForward) fTCPForwards.get(i);
                    byte[] bytes = Serializer.serialize(forward);

                    // Write file
                    File f = new File("TCPForwards/" + forward.getName() + ".tcf");
                    if (!f.exists())
                    {
                        f.setReadable(true);
                        f.setWritable(true);
                        f.createNewFile();
                    }

                    FileOutputStream stream = new FileOutputStream("TCPForwards/" + forward.getName() + ".tcf");
                    stream.write(bytes);
                    stream.close();

                }
                catch (Exception ex)
                {
                    System.err.println(ex.getMessage());
                }
            }
        }
    }

    private void Load()
    {
        try
        {
            // Find all .tcf files
            File folder = new File("TCPForwards");
            File[] listOfFiles = folder.listFiles();
            for (int i = 0; i < listOfFiles.length; i++)
            {
                try
                {
                    File file = listOfFiles[i];
                    InputStream is = new FileInputStream(file);

                    long length = file.length();
                    byte[] bytes = new byte[(int) length];

                    int offset = 0;
                    int numRead = 0;
                    while (offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0)
                    {
                        offset += numRead;
                    }

                    TCPForward loadedForward = (TCPForward) Serializer.deserialize(bytes);

                    if (loadedForward.isStarted())
                    {
                        loadedForward.Start();
                    }
                    AddTCPForward(loadedForward);
                    is.close();
                }
                catch (Exception ex)
                {
                }
            }
        }
        catch (Exception ex)
        {
        }
        UpdateTCPForwardsTable();
    }

    public void SelectTCPForwardFromTable()
    {
        synchronized (fAddRemoveTCPForwardsLock)
        {
            fSelectedTCPForward = null;

            // Get selected TCP forward
            if (jTableTCPForwards.getSelectedRows().length > 0)
            {
                int selectedRow = jTableTCPForwards.getSelectedRow();
                String selectedForwardName = (String) jTableTCPForwards.getValueAt(selectedRow, 1);
                System.out.println("Selected " + selectedForwardName);

                for (int i = 0; i < fTCPForwards.size(); i++)
                {
                    TCPForward forward = (TCPForward) fTCPForwards.get(i);
                    if (forward.getName().equals(selectedForwardName))
                    {
                        fSelectedTCPForward = forward;

                        if (forward.isStarted())
                        {
                            jMenuItemStartStopTCPForward.setText("Stop " + forward.getName());
                        }
                        else
                        {
                            jMenuItemStartStopTCPForward.setText("Start " + forward.getName());
                        }
                        break;
                    }
                }
            }
        }
    }

    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        jPopupMenuTCPForwardsTable = new javax.swing.JPopupMenu();
        jMenuItemStartStopTCPForward = new javax.swing.JMenuItem();
        jMenuItemEdit = new javax.swing.JMenuItem();
        jMenuItemAccessList = new javax.swing.JMenuItem();
        jSeparator1 = new javax.swing.JPopupMenu.Separator();
        jMenuItemDeleteForward = new javax.swing.JMenuItem();
        popupMenuTray = new java.awt.PopupMenu();
        menuItemShowHide = new java.awt.MenuItem();
        jScrollPane1 = new javax.swing.JScrollPane();
        jTableTCPForwards = new javax.swing.JTable();
        jMenuBar1 = new javax.swing.JMenuBar();
        jMenu1 = new javax.swing.JMenu();
        jMenuItem1 = new javax.swing.JMenuItem();

        jMenuItemStartStopTCPForward.setText("Start/Stop");
        jMenuItemStartStopTCPForward.setName(""); // NOI18N
        jMenuItemStartStopTCPForward.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemStartStopTCPForwardActionPerformed(evt);
            }
        });
        jPopupMenuTCPForwardsTable.add(jMenuItemStartStopTCPForward);

        jMenuItemEdit.setText("Edit");
        jMenuItemEdit.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemEditActionPerformed(evt);
            }
        });
        jPopupMenuTCPForwardsTable.add(jMenuItemEdit);

        jMenuItemAccessList.setText("Access List");
        jMenuItemAccessList.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemAccessListActionPerformed(evt);
            }
        });
        jPopupMenuTCPForwardsTable.add(jMenuItemAccessList);
        jPopupMenuTCPForwardsTable.add(jSeparator1);

        jMenuItemDeleteForward.setText("Delete");
        jMenuItemDeleteForward.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItemDeleteForwardActionPerformed(evt);
            }
        });
        jPopupMenuTCPForwardsTable.add(jMenuItemDeleteForward);

        popupMenuTray.setLabel("popupMenu1");

        menuItemShowHide.setLabel("Show/Hide");
        menuItemShowHide.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                menuItemShowHideActionPerformed(evt);
            }
        });
        popupMenuTray.add(menuItemShowHide);

        setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);
        setTitle("nCore TCP Forward Ver. 0.0.6");
        addWindowListener(new java.awt.event.WindowAdapter() {
            public void windowClosing(java.awt.event.WindowEvent evt) {
                formWindowClosing(evt);
            }
        });

        jTableTCPForwards.setModel(new javax.swing.table.DefaultTableModel(
            new Object [][] {

            },
            new String [] {
                "Status", "Name", "Listener IP", "Remote IP", "Clients Connected", "Bytes In/Out"
            }
        ) {
            boolean[] canEdit = new boolean [] {
                false, false, false, false, false, false
            };

            public boolean isCellEditable(int rowIndex, int columnIndex) {
                return canEdit [columnIndex];
            }
        });
        jTableTCPForwards.setComponentPopupMenu(jPopupMenuTCPForwardsTable);
        jTableTCPForwards.setSelectionMode(javax.swing.ListSelectionModel.SINGLE_SELECTION);
        jTableTCPForwards.getTableHeader().setReorderingAllowed(false);
        jTableTCPForwards.addMouseListener(new java.awt.event.MouseAdapter() {
            public void mouseClicked(java.awt.event.MouseEvent evt) {
                jTableTCPForwardsMouseClicked(evt);
            }
        });
        jTableTCPForwards.addKeyListener(new java.awt.event.KeyAdapter() {
            public void keyReleased(java.awt.event.KeyEvent evt) {
                jTableTCPForwardsKeyReleased(evt);
            }
        });
        jScrollPane1.setViewportView(jTableTCPForwards);
        jTableTCPForwards.getColumnModel().getColumn(0).setMinWidth(70);
        jTableTCPForwards.getColumnModel().getColumn(0).setPreferredWidth(70);
        jTableTCPForwards.getColumnModel().getColumn(0).setMaxWidth(70);

        jMenu1.setText("File");

        jMenuItem1.setText("New TCP Forward");
        jMenuItem1.addActionListener(new java.awt.event.ActionListener() {
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                jMenuItem1ActionPerformed(evt);
            }
        });
        jMenu1.add(jMenuItem1);

        jMenuBar1.add(jMenu1);

        setJMenuBar(jMenuBar1);

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());
        getContentPane().setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 964, Short.MAX_VALUE)
                .addContainerGap())
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGroup(layout.createSequentialGroup()
                .addContainerGap()
                .addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 448, Short.MAX_VALUE)
                .addContainerGap())
        );

        pack();
    }// </editor-fold>//GEN-END:initComponents

    private void jMenuItem1ActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItem1ActionPerformed
    {//GEN-HEADEREND:event_jMenuItem1ActionPerformed
        try
        {
            Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
            frmNewTCPForward frm = new frmNewTCPForward(this);

            int w = frm.getSize().width;
            int h = frm.getSize().height;
            int x = (dim.width - w) / 2;
            int y = (dim.height - h) / 2;

            frm.setLocation(x, y);
            frm.setVisible(true);
        }
        catch (Exception ex)
        {
            JOptionPane.showMessageDialog(null, ex.getMessage());
        }
    }//GEN-LAST:event_jMenuItem1ActionPerformed

    private void jTableTCPForwardsMouseClicked(java.awt.event.MouseEvent evt)//GEN-FIRST:event_jTableTCPForwardsMouseClicked
    {//GEN-HEADEREND:event_jTableTCPForwardsMouseClicked
        SelectTCPForwardFromTable();
    }//GEN-LAST:event_jTableTCPForwardsMouseClicked

    private void jMenuItemStartStopTCPForwardActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemStartStopTCPForwardActionPerformed
    {//GEN-HEADEREND:event_jMenuItemStartStopTCPForwardActionPerformed
        synchronized (fAddRemoveTCPForwardsLock)
        {
            try
            {
                if (fSelectedTCPForward != null)
                {
                    if (jMenuItemStartStopTCPForward.getText().startsWith("Start"))
                    {
                        fSelectedTCPForward.Start();
                        jMenuItemStartStopTCPForward.setText("Stop " + fSelectedTCPForward.getName());
                    }
                    else
                    {
                        fSelectedTCPForward.Stop();
                        jMenuItemStartStopTCPForward.setText("Start " + fSelectedTCPForward.getName());
                    }
                }
            }
            catch (Exception ex)
            {
                JOptionPane.showMessageDialog(null, ex.getMessage());
            }
        }

        Save();
    }//GEN-LAST:event_jMenuItemStartStopTCPForwardActionPerformed

    // Delete TCP Forward
    private void jMenuItemDeleteForwardActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemDeleteForwardActionPerformed
    {//GEN-HEADEREND:event_jMenuItemDeleteForwardActionPerformed
        synchronized (fAddRemoveTCPForwardsLock)
        {
            try
            {
                if (fSelectedTCPForward != null)
                {
                    int answer = JOptionPane.showConfirmDialog(null, "Do you want to delete " + fSelectedTCPForward.getName(), "Delete", JOptionPane.YES_NO_OPTION);
                    if (answer == JOptionPane.YES_OPTION)
                    {
                        fSelectedTCPForward.Stop();
                        RemoveTCPForward(fSelectedTCPForward);

                        File f = new File("TCPForwards\\" + fSelectedTCPForward.getName() + ".tcf");
                        if (f.exists() && f.isFile())
                        {
                            if (f.delete())
                            {
                                int a = 1;
                            }
                        }

                        fSelectedTCPForward = null;

                    }
                }

                Save();
            }
            catch (Exception ex)
            {
            }
        }

        Save();
    }//GEN-LAST:event_jMenuItemDeleteForwardActionPerformed

    // Edit TCP Forward
    private void jMenuItemEditActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemEditActionPerformed
    {//GEN-HEADEREND:event_jMenuItemEditActionPerformed
        try
        {
            if (fSelectedTCPForward != null)
            {
                Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
                frmNewTCPForward frm = new frmNewTCPForward(this, fSelectedTCPForward);

                int w = frm.getSize().width;
                int h = frm.getSize().height;
                int x = (dim.width - w) / 2;
                int y = (dim.height - h) / 2;

                frm.setLocation(x, y);
                frm.setVisible(true);
            }
        }
        catch (Exception ex)
        {
            System.err.println(ex.getMessage());
        }
    }//GEN-LAST:event_jMenuItemEditActionPerformed

    private void jTableTCPForwardsKeyReleased(java.awt.event.KeyEvent evt)//GEN-FIRST:event_jTableTCPForwardsKeyReleased
    {//GEN-HEADEREND:event_jTableTCPForwardsKeyReleased
        SelectTCPForwardFromTable();
    }//GEN-LAST:event_jTableTCPForwardsKeyReleased

    private void menuItemShowHideActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_menuItemShowHideActionPerformed
    {//GEN-HEADEREND:event_menuItemShowHideActionPerformed
        this.setVisible(!this.isVisible());
    }//GEN-LAST:event_menuItemShowHideActionPerformed

    private void jMenuItemAccessListActionPerformed(java.awt.event.ActionEvent evt)//GEN-FIRST:event_jMenuItemAccessListActionPerformed
    {//GEN-HEADEREND:event_jMenuItemAccessListActionPerformed
        try
        {
            if (fSelectedTCPForward != null)
            {
                Dimension dim = Toolkit.getDefaultToolkit().getScreenSize();
                frmForwardAccessList frm = new frmForwardAccessList(this, fSelectedTCPForward);

                int w = frm.getSize().width;
                int h = frm.getSize().height;
                int x = (dim.width - w) / 2;
                int y = (dim.height - h) / 2;

                frm.setLocation(x, y);
                frm.setVisible(true);
            }
        }
        catch (Exception ex)
        {
            System.err.println(ex.getMessage());
        }
    }//GEN-LAST:event_jMenuItemAccessListActionPerformed

    private void formWindowClosing(java.awt.event.WindowEvent evt)//GEN-FIRST:event_formWindowClosing
    {//GEN-HEADEREND:event_formWindowClosing
        int answer = JOptionPane.showConfirmDialog(null, "Are you sure you want to exit?", "Exit", JOptionPane.YES_NO_OPTION);
        if (answer == JOptionPane.YES_OPTION)
        {
            this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            this.dispose();
        }
        else
        {
            this.setDefaultCloseOperation(JFrame.DO_NOTHING_ON_CLOSE);
        }
    }//GEN-LAST:event_formWindowClosing
    // Variables declaration - do not modify//GEN-BEGIN:variables
    private javax.swing.JMenu jMenu1;
    private javax.swing.JMenuBar jMenuBar1;
    private javax.swing.JMenuItem jMenuItem1;
    private javax.swing.JMenuItem jMenuItemAccessList;
    private javax.swing.JMenuItem jMenuItemDeleteForward;
    private javax.swing.JMenuItem jMenuItemEdit;
    private javax.swing.JMenuItem jMenuItemStartStopTCPForward;
    private javax.swing.JPopupMenu jPopupMenuTCPForwardsTable;
    private javax.swing.JScrollPane jScrollPane1;
    private javax.swing.JPopupMenu.Separator jSeparator1;
    private javax.swing.JTable jTableTCPForwards;
    private java.awt.MenuItem menuItemShowHide;
    private java.awt.PopupMenu popupMenuTray;
    // End of variables declaration//GEN-END:variables
}
